﻿using System;

namespace NodeJS
{
    using NodeJS.fs;
    /// <summary>
    /// File I/O is provided by simple wrappers around standard POSIX functions.
    /// The asynchronous form always take a completion callback as its last argument. The arguments passed to the completion callback depend on the method, but the first argument is always reserved for an exception. If the operation was completed successfully, then the first argument will be null or undefined.
    /// When using the synchronous form any exceptions are immediately thrown. You can use try/catch to handle exceptions or allow them to bubble up.
    /// </summary>
    public abstract class FileSystem
    {
        /// <summary>
        /// Asynchronous rename. No arguments other than a possible exception are given to the completion callback.
        /// </summary>
        /// <param name="oldPath"></param>
        /// <param name="newPath"></param>
        /// <param name="callback"></param>
        public abstract void Rename(string oldPath, string newPath, Action<Exception> callback);

        /// <summary>
        /// Synchronous rename.
        /// </summary>
        /// <param name="oldPath"></param>
        /// <param name="newPath"></param>
        public abstract void RenameSync(string oldPath, string newPath);

        /// <summary>
        /// Asynchronous ftruncate. No arguments other than a possible exception are given to the completion callback.
        /// </summary>
        /// <param name="fd">stream.fd</param>
        /// <param name="len"></param>
        /// <param name="callback"></param>
        public abstract void Ftruncate(int fd, long len, Action<Exception> callback);

        /// <summary>
        /// Synchronous ftruncate
        /// </summary>
        /// <param name="fd">stream.fd</param>
        /// <param name="len"></param>
        public abstract void FtruncateSync(int fd, long len);

        /// <summary>
        /// Asynchronous truncate. No arguments other than a possible exception are given to the completion callback.
        /// </summary>
        /// <param name="path"></param>
        /// <param name="len"></param>
        /// <param name="callback"></param>
        public abstract void Truncate(string path, long len, Action<Exception> callback);

        /// <summary>
        /// Synchronous truncate.
        /// </summary>
        /// <param name="path"></param>
        /// <param name="len"></param>
        public abstract void TruncateSync(string path, long len);

        /// <summary>
        /// Asynchronous chown. No arguments other than a possible exception are given to the completion callback.
        /// </summary>
        /// <param name="path"></param>
        /// <param name="uid"></param>
        /// <param name="gid"></param>
        /// <param name="callback"></param>
        public abstract void Chown(string path, int uid, int gid, Action<Exception> callback);

        /// <summary>
        /// Synchronous chown.
        /// </summary>
        /// <param name="path"></param>
        /// <param name="uid"></param>
        /// <param name="gid"></param>
        public abstract void ChownSync(string path, int uid, int gid);

        /// <summary>
        /// Asynchronous fchown. No arguments other than a possible exception are given to the completion callback.
        /// </summary>
        /// <param name="fd"></param>
        /// <param name="uid"></param>
        /// <param name="gid"></param>
        /// <param name="callback"></param>
        public abstract void Fchown(int fd, int uid, int gid, Action<Exception> callback);

        /// <summary>
        /// Synchronous fchown.
        /// </summary>
        /// <param name="fd"></param>
        /// <param name="uid"></param>
        /// <param name="gid"></param>
        public abstract void FchownSync(int fd, int uid, int gid);

        /// <summary>
        /// Asynchronous lchown. No arguments other than a possible exception are given to the completion callback.
        /// </summary>
        /// <param name="path"></param>
        /// <param name="uid"></param>
        /// <param name="gid"></param>
        /// <param name="callback"></param>
        public abstract void Lchown(string path, int uid, int gid, Action<Exception> callback);

        /// <summary>
        /// Synchronous lchown.
        /// </summary>
        /// <param name="path"></param>
        /// <param name="uid"></param>
        /// <param name="gid"></param>
        public abstract void LchownSync(string path, int uid, int gid);

        /// <summary>
        /// Asynchronous chmod. No arguments other than a possible exception are given to the completion callback.
        /// </summary>
        /// <param name="path"></param>
        /// <param name="mode"></param>
        /// <param name="callback"></param>
        public abstract void Chmod(string path, int mode, Action<Exception> callback);

        /// <summary>
        /// Synchronous chmod.
        /// </summary>
        /// <param name="path"></param>
        /// <param name="mode"></param>
        public abstract void ChmodSync(string path, int mode);

        /// <summary>
        /// Asynchronous fchmod. No arguments other than a possible exception are given to the completion callback.
        /// </summary>
        /// <param name="fd"></param>
        /// <param name="mode"></param>
        /// <param name="callback"></param>
        public abstract void Fchmod(int fd, int mode, Action<Exception> callback);

        /// <summary>
        /// Synchronous fchmod.
        /// </summary>
        /// <param name="fd"></param>
        /// <param name="mode"></param>
        public abstract void FchmodSync(int fd, int mode);

        /// <summary>
        /// Asynchronous lchmod. No arguments other than a possible exception are given to the completion callback.
        /// Only available on Mac OS X.
        /// </summary>
        /// <param name="path"></param>
        /// <param name="mode"></param>
        /// <param name="callback"></param>
        public abstract void Lchmod(string path, int mode, Action<Exception> callback);

        /// <summary>
        /// Synchronous lchmod.
        /// </summary>
        /// <param name="path"></param>
        /// <param name="mode"></param>
        public abstract void LchmodSync(string path, int mode);

        /// <summary>
        /// Asynchronous stat. The callback gets two arguments (err, stats) where stats is a fs.Stats object.
        /// </summary>
        /// <param name="path"></param>
        /// <param name="callback"></param>
        public abstract void Stat(string path, Action<Exception, Stats> callback);

        /// <summary>
        /// Asynchronous lstat. The callback gets two arguments (err, stats) where stats is a fs.Stats object. lstat() is identical to stat(), except that if path is a symbolic link, then the link itself is stat-ed, not the file that it refers to.
        /// </summary>
        /// <param name="path"></param>
        /// <param name="callback"></param>
        public abstract void Lstat(string path, Action<Exception, Stats> callback);

        /// <summary>
        /// Asynchronous fstat. The callback gets two arguments (err, stats) where stats is a fs.Stats object. fstat() is identical to stat(), except that the file to be stat-ed is specified by the file descriptor fd.
        /// </summary>
        /// <param name="fd"></param>
        /// <param name="callback"></param>
        public abstract void Fstat(int fd, Action<Exception, Stats> callback);

        /// <summary>
        /// Synchronous stat. Returns an instance of fs.Stats.
        /// </summary>
        /// <param name="path"></param>
        /// <returns></returns>
        public abstract Stats StatSync(string path);

        /// <summary>
        /// Synchronous lstat. Returns an instance of fs.Stats.
        /// </summary>
        /// <param name="path"></param>
        /// <returns></returns>
        public abstract Stats LstatSync(string path);

        /// <summary>
        /// Synchronous fstat. Returns an instance of fs.Stats.
        /// </summary>
        /// <param name="fd"></param>
        /// <returns></returns>
        public abstract Stats FstatSync(int fd);

        /// <summary>
        /// Asynchronous link. No arguments other than a possible exception are given to the completion callback.
        /// </summary>
        /// <param name="srcpath"></param>
        /// <param name="dstpath"></param>
        /// <param name="callback"></param>
        public abstract void Link(string srcpath, string dstpath, Action<Exception> callback);

        /// <summary>
        /// Synchronous link.
        /// </summary>
        /// <param name="srcpath"></param>
        /// <param name="dstpath"></param>
        public abstract void LinkSync(string srcpath, string dstpath);

        /// <summary>
        /// Asynchronous symlink. No arguments other than a possible exception are given to the completion callback.  Note that Windows junction points require the destination path to be absolute. When using 'junction', the destination argument will automatically be normalized to absolute path.
        /// </summary>
        /// <param name="srcpath"></param>
        /// <param name="dstpath"></param>
        /// <param name="type">Can be either 'dir', 'file', or 'junction' (default is 'file'). It is only used on Windows (ignored on other platforms).</param>
        /// <param name="callback"></param>
        public abstract void Symlink(string srcpath, string dstpath, string type, Action<Exception> callback);

        /// <summary>
        /// Asynchronous symlink. No arguments other than a possible exception are given to the completion callback.  Note that Windows junction points require the destination path to be absolute. When using 'junction', the destination argument will automatically be normalized to absolute path.
        /// </summary>
        /// <param name="srcpath"></param>
        /// <param name="dstpath"></param>
        /// <param name="callback"></param>
        public abstract void Symlink(string srcpath, string dstpath, Action<Exception> callback);

        /// <summary>
        /// Synchronous symlink.
        /// </summary>
        /// <param name="srcpath"></param>
        /// <param name="dstpath"></param>
        /// <param name="type">Can be either 'dir', 'file', or 'junction' (default is 'file'). It is only used on Windows (ignored on other platforms).</param>
        public abstract void SymlinkSync(string srcpath, string dstpath, string type = "file");

        /// <summary>
        /// Asynchronous readlink.
        /// </summary>
        /// <param name="path"></param>
        /// <param name="callback">The callback gets two arguments (err, linkString).</param>
        public abstract void Readlink(string path, Action<Exception, string> callback);

        /// <summary>
        /// Synchronous readlink. Returns the symbolic link's string value.
        /// </summary>
        /// <param name="path"></param>
        /// <returns></returns>
        public abstract string ReadlinkSync(string path);

        /// <summary>
        /// Asynchronous realpath. The callback gets two arguments (err, resolvedPath). May use process.cwd to resolve relative paths.
        /// </summary>
        /// <param name="path"></param>
        /// <param name="cache">cache is an object literal of mapped paths that can be used to force a specific path resolution or avoid additional fs.stat calls for known real paths.</param>
        /// <param name="callback"></param>
        public abstract void Realpath(string path, object cache, Action<Exception, string> callback);

        /// <summary>
        /// Asynchronous realpath. The callback gets two arguments (err, resolvedPath). May use process.cwd to resolve relative paths.
        /// </summary>
        /// <param name="path"></param>
        /// <param name="callback"></param>
        public abstract void Realpath(string path, Action<Exception, string> callback);

        /// <summary>
        /// Synchronous realpath. Returns the resolved path.
        /// </summary>
        /// <param name="path"></param>
        /// <param name="cache"></param>
        /// <returns></returns>
        public abstract string RealpathSync(string path, object cache = null);

        /// <summary>
        /// Asynchronous unlink. No arguments other than a possible exception are given to the completion callback.
        /// </summary>
        /// <param name="path"></param>
        /// <param name="callback"></param>
        public abstract void Unlink(string path, Action<Exception> callback);

        /// <summary>
        /// Synchronous unlink.
        /// </summary>
        /// <param name="path"></param>
        public abstract void UnlinkSync(string path);

        /// <summary>
        /// Asynchronous rmdir. No arguments other than a possible exception are given to the completion callback.
        /// </summary>
        /// <param name="path"></param>
        /// <param name="callback"></param>
        public abstract void Rmdir(string path, Action<Exception> callback);

        /// <summary>
        /// Synchronous rmdir.
        /// </summary>
        /// <param name="path"></param>
        public abstract void RmdirSync(string path);

        /// <summary>
        /// Asynchronous mkdir. No arguments other than a possible exception are given to the completion callback.
        /// </summary>
        /// <param name="path"></param>
        /// <param name="mode">mode defaults to 0777.</param>
        /// <param name="callback"></param>
        public abstract void Mkdir(string path, int mode, Action<Exception> callback);

        /// <summary>
        /// Asynchronous mkdir. No arguments other than a possible exception are given to the completion callback.
        /// </summary>
        /// <param name="path"></param>
        /// <param name="callback"></param>
        public abstract void Mkdir(string path, Action<Exception> callback);

        /// <summary>
        /// Synchronous mkdir.
        /// </summary>
        /// <param name="path"></param>
        /// <param name="mode"></param>
        public abstract void MkdirSync(string path, int mode = 0777);

        /// <summary>
        /// Asynchronous readdir. Reads the contents of a directory. 
        /// </summary>
        /// <param name="path"></param>
        /// <param name="callback">The callback gets two arguments (err, files) where files is an array of the names of the files in the directory excluding '.' and '..'.</param>
        public abstract void Readdir(string path, Action<Exception, string[]> callback);

        /// <summary>
        /// Synchronous readdir. Returns an array of filenames excluding '.' and '..'.
        /// </summary>
        /// <param name="path"></param>
        public abstract string[] ReaddirSync(string path);

        /// <summary>
        /// Asynchronous close. No arguments other than a possible exception are given to the completion callback.
        /// </summary>
        /// <param name="fd"></param>
        /// <param name="callback"></param>
        public abstract void Close(int fd, Action<Exception> callback);

        /// <summary>
        /// Synchronous close.
        /// </summary>
        /// <param name="fd"></param>
        public abstract void CloseSync(int fd);


        /// <summary>
        /// Asynchronous file open.
        /// </summary>
        /// <param name="path"></param>
        /// <param name="flags">
        /// <para>'r' - Open file for reading. An exception occurs if the file does not exist.</para>
        /// <para>'r+' - Open file for reading and writing. An exception occurs if the file does not exist.</para>
        /// <para>'rs' - Open file for reading in synchronous mode. Instructs the operating system to bypass the local file system cache.
        /// This is primarily useful for opening files on NFS mounts as it allows you to skip the potentially stale local cache. It has a very real impact on I/O performance so don't use this flag unless you need it.
        /// Note that this doesn't turn fs.open() into a synchronous blocking call. If that's what you want then you should be using fs.openSync()</para>
        /// <para>'rs+' - Open file for reading and writing, telling the OS to open it synchronously. See notes for 'rs' about using this with caution.</para>
        /// <para>'w' - Open file for writing. The file is created (if it does not exist) or truncated (if it exists).</para>
        /// <para>'wx' - Like 'w' but fails if path exists.</para>
        /// <para>'w+' - Open file for reading and writing. The file is created (if it does not exist) or truncated (if it exists).</para>
        /// <para>'wx+' - Like 'w+' but fails if path exists.</para>
        /// <para>'a' - Open file for appending. The file is created if it does not exist.</para>
        /// <para>'ax' - Like 'a' but fails if path exists.</para>
        /// <para>'a+' - Open file for reading and appending. The file is created if it does not exist.</para>
        /// <para>'ax+' - Like 'a+' but fails if path exists.</para>
        /// </param>
        /// <param name="mode">mode sets the file mode (permission and sticky bits), but only if the file was created. It defaults to 0666, readable and writeable.</param>
        /// <param name="callback">The callback gets two arguments (err, fd).</param>
        public abstract void Open(string path, string flags, int mode, Action<Exception, int> callback);

        /// <summary>
        /// Asynchronous file open.
        /// </summary>
        /// <param name="path"></param>
        /// <param name="flags">
        /// <para>'r' - Open file for reading. An exception occurs if the file does not exist.</para>
        /// <para>'r+' - Open file for reading and writing. An exception occurs if the file does not exist.</para>
        /// <para>'rs' - Open file for reading in synchronous mode. Instructs the operating system to bypass the local file system cache.
        /// This is primarily useful for opening files on NFS mounts as it allows you to skip the potentially stale local cache. It has a very real impact on I/O performance so don't use this flag unless you need it.
        /// Note that this doesn't turn fs.open() into a synchronous blocking call. If that's what you want then you should be using fs.openSync()</para>
        /// <para>'rs+' - Open file for reading and writing, telling the OS to open it synchronously. See notes for 'rs' about using this with caution.</para>
        /// <para>'w' - Open file for writing. The file is created (if it does not exist) or truncated (if it exists).</para>
        /// <para>'wx' - Like 'w' but fails if path exists.</para>
        /// <para>'w+' - Open file for reading and writing. The file is created (if it does not exist) or truncated (if it exists).</para>
        /// <para>'wx+' - Like 'w+' but fails if path exists.</para>
        /// <para>'a' - Open file for appending. The file is created if it does not exist.</para>
        /// <para>'ax' - Like 'a' but fails if path exists.</para>
        /// <para>'a+' - Open file for reading and appending. The file is created if it does not exist.</para>
        /// <para>'ax+' - Like 'a+' but fails if path exists.</para>
        /// </param>
        /// <param name="callback">The callback gets two arguments (err, fd).</param>
        public abstract void Open(string path, string flags, Action<Exception, int> callback);

        /// <summary>
        /// Synchronous version of fs.open()
        /// </summary>
        /// <param name="path"></param>
        /// <param name="flags">
        /// <para>'r' - Open file for reading. An exception occurs if the file does not exist.</para>
        /// <para>'r+' - Open file for reading and writing. An exception occurs if the file does not exist.</para>
        /// <para>'rs' - Open file for reading in synchronous mode. Instructs the operating system to bypass the local file system cache.
        /// This is primarily useful for opening files on NFS mounts as it allows you to skip the potentially stale local cache. It has a very real impact on I/O performance so don't use this flag unless you need it.
        /// Note that this doesn't turn fs.open() into a synchronous blocking call. If that's what you want then you should be using fs.openSync()</para>
        /// <para>'rs+' - Open file for reading and writing, telling the OS to open it synchronously. See notes for 'rs' about using this with caution.</para>
        /// <para>'w' - Open file for writing. The file is created (if it does not exist) or truncated (if it exists).</para>
        /// <para>'wx' - Like 'w' but fails if path exists.</para>
        /// <para>'w+' - Open file for reading and writing. The file is created (if it does not exist) or truncated (if it exists).</para>
        /// <para>'wx+' - Like 'w+' but fails if path exists.</para>
        /// <para>'a' - Open file for appending. The file is created if it does not exist.</para>
        /// <para>'ax' - Like 'a' but fails if path exists.</para>
        /// <para>'a+' - Open file for reading and appending. The file is created if it does not exist.</para>
        /// <para>'ax+' - Like 'a+' but fails if path exists.</para>
        /// </param>
        /// <param name="mode"></param>
        /// <returns></returns>
        public abstract int OpenSync(string path, string flags, int mode = 0666);

        /// <summary>
        /// Change file timestamps of the file referenced by the supplied path.
        /// </summary>
        /// <param name="path"></param>
        /// <param name="atime"></param>
        /// <param name="mtime"></param>
        /// <param name="callback"></param>
        public abstract void Utimes(string path, DateTime atime, DateTime mtime, Action callback);

        /// <summary>
        /// Change file timestamps of the file referenced by the supplied path.
        /// </summary>
        /// <param name="path"></param>
        /// <param name="atime"></param>
        /// <param name="mtime"></param>
        public abstract void UtimesSync(string path, DateTime atime, DateTime mtime);

        /// <summary>
        /// Change the file timestamps of a file referenced by the supplied file descriptor.
        /// </summary>
        /// <param name="fd"></param>
        /// <param name="atime"></param>
        /// <param name="mtime"></param>
        /// <param name="callback"></param>
        public abstract void Futimes(int fd, DateTime atime, DateTime mtime, Action callback);

        /// <summary>
        /// Change the file timestamps of a file referenced by the supplied file descriptor.
        /// </summary>
        /// <param name="fd"></param>
        /// <param name="atime"></param>
        /// <param name="mtime"></param>
        public abstract void FutimesSync(int fd, DateTime atime, DateTime mtime);

        /// <summary>
        /// Asynchronous fsync. No arguments other than a possible exception are given to the completion callback.
        /// </summary>
        /// <param name="fd"></param>
        /// <param name="callback"></param>
        public abstract void Fsync(int fd, Action<Exception> callback);

        /// <summary>
        /// Synchronous fsync.
        /// </summary>
        /// <param name="fd"></param>
        public abstract void FsyncSync(int fd);

        /// <summary>
        /// Write buffer to the file specified by fd.
        /// Note that it is unsafe to use fs.write multiple times on the same file without waiting for the callback. For this scenario, fs.createWriteStream is strongly recommended.
        /// On Linux, positional writes don't work when the file is opened in append mode. The kernel ignores the position argument and always appends the data to the end of the file.
        /// </summary>
        /// <param name="fd"></param>
        /// <param name="buffer"></param>
        /// <param name="offset">offset and length determine the part of the buffer to be written.</param>
        /// <param name="length">offset and length determine the part of the buffer to be written.</param>
        /// <param name="position">position refers to the offset from the beginning of the file where this data should be written. If position is null, the data will be written at the current position. See pwrite(2).</param>
        /// <param name="callback">The callback will be given three arguments (err, written, buffer) where written specifies how many bytes were written from buffer.</param>
        public abstract void Write(int fd, Buffer buffer, long offset, long length, long? position, Action<Exception, long, Buffer> callback);

        /// <summary>
        /// Synchronous version of fs.write().
        /// </summary>
        /// <param name="fd"></param>
        /// <param name="buffer"></param>
        /// <param name="offset"></param>
        /// <param name="length"></param>
        /// <param name="position"></param>
        /// <returns>Returns the number of bytes written.</returns>
        public abstract long WriteSync(int fd, Buffer buffer, long offset, long length, long? position);

        /// <summary>
        /// Read data from the file specified by fd.
        /// </summary>
        /// <param name="fd"></param>
        /// <param name="buffer">buffer is the buffer that the data will be written to.</param>
        /// <param name="offset">offset is the offset in the buffer to start writing at.</param>
        /// <param name="length">length is an integer specifying the number of bytes to read.</param>
        /// <param name="position">position is an integer specifying where to begin reading from in the file. If position is null, data will be read from the current file position.</param>
        /// <param name="callback">The callback is given the three arguments, (err, bytesRead, buffer).</param>
        public abstract void Read(int fd, Buffer buffer, long offset, long length, long? position, Action<Exception, long, Buffer> callback);

        /// <summary>
        /// Synchronous version of fs.read.
        /// </summary>
        /// <param name="fd"></param>
        /// <param name="fd"></param>
        /// <param name="buffer">buffer is the buffer that the data will be written to.</param>
        /// <param name="offset">offset is the offset in the buffer to start writing at.</param>
        /// <param name="length">length is an integer specifying the number of bytes to read.</param>
        /// <param name="position">position is an integer specifying where to begin reading from in the file. If position is null, data will be read from the current file position.</param>
        /// <returns>Returns the number of bytesRead.</returns>
        public abstract long ReadSync(int fd, Buffer buffer, long offset, long length, long? position);

        /// <summary>
        /// Asynchronously reads the entire contents of a file.
        /// </summary>
        /// <param name="filename"></param>
        /// <param name="callback">The callback is passed two arguments (err, data), where data is the contents of the file.
        /// If no encoding is specified, then the raw buffer is returned.</param>
        public abstract void ReadFile(string filename, Action<Exception, StringOrBuffer> callback);

        /// <summary>
        /// Asynchronously reads the entire contents of a file.
        /// </summary>
        /// <param name="filename"></param>
        /// <param name="options">
        /// options Object:
        /// <para>encoding String | Null default = null</para>
        /// <para>flag String default = 'r'</para>
        /// </param>
        /// <param name="callback">The callback is passed two arguments (err, data), where data is the contents of the file.
        /// If no encoding is specified, then the raw buffer is returned.</param>
        public abstract void ReadFile(string filename, object options, Action<Exception, StringOrBuffer> callback);

        /// <summary>
        /// Synchronous version of fs.readFile.
        /// </summary>
        /// <param name="filename"></param>
        /// <param name="options">
        /// options Object:
        /// <para>encoding String | Null default = null</para>
        /// <para>flag String default = 'r'</para>
        /// </param>
        /// <returns>Returns the contents of the filename.
        /// If the encoding option is specified then this function returns a string. Otherwise it returns a buffer.
        /// </returns>
        public abstract StringOrBuffer ReadFileSync(string filename, object options = null);

        /// <summary>
        /// Asynchronously writes data to a file, replacing the file if it already exists.
        /// </summary>
        /// <param name="filename"></param>
        /// <param name="data"></param>
        /// <param name="callback"></param>
        public abstract void WriteFile(string filename, StringOrBuffer data, Action<Exception> callback);

        /// <summary>
        /// Asynchronously writes data to a file, replacing the file if it already exists.
        /// </summary>
        /// <param name="filename"></param>
        /// <param name="data"></param>
        /// <param name="options">options Object
        /// <para>encoding String | Null default = 'utf8'</para>
        /// <para>mode Number default = 438 (aka 0666 in Octal)</para>
        /// <para>flag String default = 'w'</para>
        /// The encoding option is ignored if data is a buffer. It defaults to 'utf8'.
        /// </param>
        /// <param name="callback"></param>
        public abstract void WriteFile(string filename, StringOrBuffer data, object options, Action<Exception> callback);

        /// <summary>
        /// The synchronous version of fs.writeFile.
        /// </summary>
        /// <param name="filename"></param>
        /// <param name="data"></param>
        /// <param name="options">options Object
        /// <para>encoding String | Null default = 'utf8'</para>
        /// <para>mode Number default = 438 (aka 0666 in Octal)</para>
        /// <para>flag String default = 'w'</para>
        /// The encoding option is ignored if data is a buffer. It defaults to 'utf8'.
        /// </param>
        public abstract void WriteFileSync(string filename, StringOrBuffer data, object options = null);

        /// <summary>
        /// Asynchronously append data to a file, creating the file if it not yet exists.
        /// </summary>
        /// <param name="filename"></param>
        /// <param name="data"></param>
        /// <param name="callback"></param>
        public abstract void AppendFile(string filename, StringOrBuffer data, Action<Exception> callback);

        /// <summary>
        /// Asynchronously append data to a file, creating the file if it not yet exists.
        /// </summary>
        /// <param name="filename"></param>
        /// <param name="data"></param>
        /// <param name="options">options Object
        /// <para>encoding String | Null default = 'utf8'</para>
        /// <para>mode Number default = 438 (aka 0666 in Octal)</para>
        /// <para>flag String default = 'a'</para>
        /// </param>
        /// <param name="callback"></param>
        public abstract void AppendFile(string filename, StringOrBuffer data, object options, Action<Exception> callback);
        
        /// <summary>
        /// The synchronous version of fs.appendFile.
        /// </summary>
        /// <param name="filename"></param>
        /// <param name="data"></param>
        /// <param name="options">options Object
        /// <para>encoding String | Null default = 'utf8'</para>
        /// <para>mode Number default = 438 (aka 0666 in Octal)</para>
        /// <para>flag String default = 'a'</para>
        /// </param>
        public abstract void AppendFileSync(string filename, StringOrBuffer data, object options = null);

        /// <summary>
        /// Test whether or not the given path exists by checking with the file system.
        /// </summary>
        /// <param name="path"></param>
        /// <param name="callback">Then call the callback argument with either true or false.</param>
        public abstract void Exists(string path, Action<bool> callback);

        /// <summary>
        /// Synchronous version of fs.exists.
        /// </summary>
        /// <param name="path"></param>
        /// <returns></returns>
        public abstract bool ExistsSync(string path);

        /// <summary>
        /// 
        /// </summary>
        /// <param name="path"></param>
        /// <param name="options">options is an object with the following defaults:
        /// <para>{ flags: 'r', encoding: null, fd: null, mode: 0666, autoClose: true }</para>
        /// <para>options can include start and end values to read a range of bytes from the file instead of the entire file. Both start and end are inclusive and start at 0.</para>
        /// <para>The encoding can be 'utf8', 'ascii', or 'base64'.</para>
        /// <para>If autoClose is false, then the file descriptor won't be closed, even if there's an error. It is your responsiblity to close it and make sure there's no file descriptor leak. If autoClose is set to true (default behavior), on error or end the file descriptor will be closed automatically.</para>
        /// </param>
        /// <returns>Returns a new ReadStream object (See Readable Stream).</returns>
        public abstract ReadStream CreateReadStream(string path, object options = null);

        /// <summary>
        /// 
        /// </summary>
        /// <param name="path"></param>
        /// <param name="options">
        /// options is an object with the following defaults:
        /// <para>{ flags: 'w', encoding: null, mode: 0666 }</para>
        /// <para>options may also include a start option to allow writing data at some position past the beginning of the file.</para>
        /// <para>Modifying a file rather than replacing it may require a flags mode of r+ rather than the default mode w.</para>
        /// </param>
        /// <returns>Returns a new WriteStream object (See Writable Stream).</returns>
        public abstract WriteStream CreateWriteStream(string path, object options = null);
    }
}
